home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / lfs / lfsSegUsage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  32.7 KB  |  1,181 lines

  1. /* 
  2.  * lfsSegUsage.c --
  3.  *
  4.  *    Routines and data structures providing knowledge more segments 
  5.  *    block usage.  This module managers the segment usage array and
  6.  *    implements the selection of the next segment to write and to
  7.  *    clean.  This module should be notified of all block deallocation
  8.  *    inorder to make intelligent choices.  The module also detects 
  9.  *    "logwrap" and starts with block cleaner and generates "df"
  10.  *    numbers.
  11.  *
  12.  *     For each LFS, the module classifies segment into one of three classes:
  13.  *    clean, dirty, or full.   A segment is clean if it
  14.  *    contains no live data.  A segment is dirty if it is not clean
  15.  *    and has fewer activeBytes than permitable. A segment is full if
  16.  *    it is neither clean nor dirty.
  17.  *
  18.  * Copyright 1989 Regents of the University of California
  19.  * Permission to use, copy, modify, and distribute this
  20.  * software and its documentation for any purpose and without
  21.  * fee is hereby granted, provided that the above copyright
  22.  * notice appear in all copies.  The University of California
  23.  * makes no representations about the suitability of this
  24.  * software for any purpose.  It is provided "as is" without
  25.  * express or implied warranty.
  26.  */
  27.  
  28. #ifndef lint
  29. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/lfs/lfsSegUsage.c,v 1.18 92/06/01 15:09:01 kupfer Exp $ SPRITE (Berkeley)";
  30. #endif /* not lint */
  31.  
  32. #include <lfsInt.h>
  33. #include <lfsSeg.h>
  34. #include <lfsStableMemInt.h>
  35. #include <lfsSegUsageInt.h>
  36.  
  37. #include <fsdm.h>
  38.  
  39. int lfsMinCleanThreshold = 5;
  40.  
  41. /*
  42.  *----------------------------------------------------------------------
  43.  *
  44.  * LfsSegUsageFreeBlocks --
  45.  *
  46.  *    Inform the segment usage manager that blocks are no long needed.
  47.  *
  48.  * Results:
  49.  *    SUCCESS if the blocks are valid.
  50.  *
  51.  * Side effects:
  52.  *    Seg usage map.
  53.  *
  54.  *----------------------------------------------------------------------
  55.  */
  56.  
  57. ReturnStatus
  58. LfsSegUsageFreeBlocks(lfsPtr, blockSize, blockArrayLen, blockArrayPtr)
  59.     Lfs        *lfsPtr;    /* File system of interest. */
  60.     int        blockSize;    /* Size in bytes of blocks to free. */
  61.     int             blockArrayLen; /* Number of elements in blockArrayPtr. */
  62.     LfsDiskAddr *blockArrayPtr;            /* Array of disk addresses. */
  63. {
  64.     int        i;
  65.     LfsDiskAddr    diskAddress;
  66.  
  67.     for (i = 0; i < blockArrayLen; i++) {
  68.     diskAddress = *blockArrayPtr;
  69.     if (!LfsIsNilDiskAddr(diskAddress)) {
  70.         LfsSetNilDiskAddr(blockArrayPtr);
  71.         LFS_STATS_INC(lfsPtr->stats.segusage.blocksFreed);
  72.         LFS_STATS_ADD(lfsPtr->stats.segusage.bytesFreed,  blockSize);
  73.         LfsSetSegUsage(lfsPtr,
  74.         LfsDiskAddrToSegmentNum(lfsPtr, diskAddress), -blockSize);
  75.     }
  76.     blockArrayPtr++;
  77.     }
  78.     return SUCCESS;
  79. }
  80.  
  81. /*
  82.  *----------------------------------------------------------------------
  83.  *
  84.  * SegUsageAllocateBytes --
  85.  *
  86.  *    Inform the file system for the need to allocate some bytes.
  87.  *
  88.  * Results:
  89.  *    SUCCESS if the allocation works, failure otherwise.
  90.  *
  91.  * Side effects:
  92.  *    
  93.  *
  94.  *----------------------------------------------------------------------
  95.  */
  96. ReturnStatus 
  97. LfsSegUsageAllocateBytes(lfsPtr, numBytes)
  98.        Lfs    *lfsPtr;    /* File system of interest. */
  99.        int    numBytes;       /* Number of file system bytes needed. */
  100. {
  101.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  102.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  103.     int blocks;
  104.     char errMsg[1024];
  105.  
  106.     blocks = LfsBytesToBlocks(lfsPtr, numBytes);
  107.     if (cp->freeBlocks - blocks > usagePtr->params.minFreeBlocks) { 
  108.     return SUCCESS;
  109.     }
  110.     sprintf(errMsg, "LfsSegUsageAllocateBytes: no space on %s.\n",
  111.         lfsPtr->name);    /* DEBUG */
  112.     if (Timer_OkToWhine(errMsg)) {
  113.     printf(errMsg);
  114.     }
  115.     return FS_NO_DISK_SPACE;
  116. }
  117.  
  118. /*
  119.  *----------------------------------------------------------------------
  120.  *
  121.  * SegUsageFreeBytes --
  122.  *
  123.  *    Inform the file system that the previously allocated bytes are 
  124.  *    nolonger needed or have already been allocated on disk.
  125.  *
  126.  * Results:
  127.  *    SUCCESS if the allocation works, failure otherwise.
  128.  *
  129.  * Side effects:
  130.  *    
  131.  *
  132.  *----------------------------------------------------------------------
  133.  */
  134. ReturnStatus 
  135. LfsSegUsageFreeBytes(lfsPtr,numBytes)
  136.        Lfs    *lfsPtr;    /* File system of interest. */
  137.        int    numBytes;       /* Number of file system bytes to free. */
  138. {
  139.     return SUCCESS;
  140. }
  141.  
  142. /*
  143.  *----------------------------------------------------------------------
  144.  *
  145.  * LfsCheckRead --
  146.  *
  147.  *    Check to see if it is ok to read the specified byte range. 
  148.  *
  149.  * Results:
  150.  *
  151.  * Side effects:
  152.  *    
  153.  *
  154.  *----------------------------------------------------------------------
  155.  */
  156. void
  157. LfsCheckRead(lfsPtr,diskAddress, numBytes)
  158.        Lfs    *lfsPtr;    /* File system of interest. */
  159.        LfsDiskAddr   diskAddress;  /* Disk address of read. */
  160.        int    numBytes;          /* Number of bytes being read. */
  161. {
  162.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  163.     register LfsSegUsageEntry  *s;
  164.     int segNo, segNo2, blocks;
  165.     ReturnStatus      status;
  166.     LfsDiskAddr newDiskAddr;
  167.     LfsStableMemEntry smemEntry;
  168.  
  169.     segNo = LfsDiskAddrToSegmentNum(lfsPtr, diskAddress);
  170.     if ((segNo < 0) || (segNo >=  usagePtr->params.numberSegments)) {
  171.     panic("LfsOkToRead bad segment number %d\n", segNo);
  172.     return;
  173.     }
  174.     status = LfsStableMemFetch(&(usagePtr->stableMem),segNo,0,&smemEntry);
  175.     if (status != SUCCESS) {
  176.     panic("LfsOkToRead can't fetch usage array block.\n");
  177.     }
  178.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  179.  
  180.     if (s->flags & LFS_SEG_USAGE_CLEAN) {
  181.     panic("LfsOkToRead read from clean segment: %s\n",
  182.         lfsPtr->name);
  183.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  184.     return;
  185.     }
  186.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  187.     blocks = LfsBytesToBlocks(lfsPtr, numBytes)-1;
  188.     LfsDiskAddrPlusOffset(diskAddress, blocks, &newDiskAddr);
  189.     segNo2 = LfsDiskAddrToSegmentNum(lfsPtr, newDiskAddr);
  190.     if (segNo2 != segNo) {
  191.     printf("LfsOkToRead read over segment boundary.\n");
  192.     }
  193.  
  194. }
  195.  
  196. /*
  197.  *----------------------------------------------------------------------
  198.  *
  199.  * LfsSetSegUsage --
  200.  *
  201.  *    Set the usage level of the specified segment.
  202.  *
  203.  * Results:
  204.  *    None
  205.  *
  206.  * Side effects:
  207.  *    Seg usage array may be modified.
  208.  *
  209.  *----------------------------------------------------------------------
  210.  */
  211.  
  212. void
  213. LfsSetSegUsage(lfsPtr, segNumber, activeBytes)
  214.     Lfs        *lfsPtr;    /* File system of interest. */
  215.     int        segNumber;     /* Segment number in file system. */
  216.     int        activeBytes;    /* Usage level Change. */
  217. {
  218.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  219.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  220.     register LfsSegUsageEntry *s;
  221.     ReturnStatus      status;
  222.     LfsStableMemEntry smemEntry;
  223.  
  224.     LFS_STATS_INC(lfsPtr->stats.segusage.usageSet);
  225.     if ((segNumber < 0) || (segNumber >= usagePtr->params.numberSegments)) {
  226.     panic("LfsSetSegUsage bad segment number %d\n", segNumber);
  227.     return;
  228.     }
  229.     if (activeBytes == 0) {
  230.     printf("LfsSetSegUsage: SegNo %d activeBytes %d\n", segNumber, 
  231.             activeBytes);
  232.     }
  233.     /*
  234.      * We special case the current segment we are writing to.
  235.      */
  236.     if (segNumber == cp->currentSegment) {
  237.     int oldActiveBytes = cp->curSegActiveBytes;
  238.     cp->curSegActiveBytes += activeBytes;
  239.     if (cp->curSegActiveBytes < 0) {
  240.          printf("LfsSetSegUsage: Warning activeBytes for segment %d is %d\n",
  241.             segNumber, cp->curSegActiveBytes);
  242.         cp->curSegActiveBytes = 0;
  243.     }
  244.     cp->freeBlocks += (LfsBytesToBlocks(lfsPtr, oldActiveBytes) - 
  245.                LfsBytesToBlocks(lfsPtr, cp->curSegActiveBytes));
  246.     return;
  247.     }
  248.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNumber, 
  249.                 LFS_STABLE_MEM_MAY_DIRTY, &smemEntry);
  250.     if (status != SUCCESS) {
  251.     panic("LfsSetSegUsage can't fetch usage array block.\n");
  252.     return;
  253.     }
  254.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  255.  
  256.  
  257.     activeBytes = s->activeBytes + activeBytes;
  258.     if (activeBytes < 0) {
  259.      printf("LfsSetSegUsage: Warning activeBytes for segment %d is %d\n",
  260.         segNumber, activeBytes);
  261.     activeBytes = 0;
  262.     }
  263.     cp->freeBlocks += (LfsBytesToBlocks(lfsPtr, s->activeBytes) - 
  264.                 LfsBytesToBlocks(lfsPtr, activeBytes));
  265.     if (s->flags & LFS_SEG_USAGE_CLEAN) {
  266.     panic("LfsSetSegUsage called on a clean segment (%d): %s\n", 
  267.         segNumber, lfsPtr->name);
  268.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  269.     return;
  270.     }
  271.     /*
  272.      * Is it moving onto dirty list?
  273.      */
  274.     if (activeBytes <= cp->dirtyActiveBytes) {
  275.     if (s->flags & LFS_SEG_USAGE_DIRTY) { 
  276.         /*
  277.          * All ready on dirty list then do nothing.
  278.          */
  279.         s->activeBytes = activeBytes;
  280.         LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  281.         return;
  282.     }
  283.         s->activeBytes = activeBytes;
  284.     s->flags |= LFS_SEG_USAGE_DIRTY;
  285.     cp->numDirty++;
  286.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  287.     return;
  288.     }
  289.     /*
  290.      * Segment is not clean or dirty just full.
  291.      */
  292.     if (s->flags & LFS_SEG_USAGE_DIRTY) { 
  293.     s->flags &= ~LFS_SEG_USAGE_DIRTY;
  294.     cp->numDirty--;
  295.     }
  296.     s->activeBytes = activeBytes;
  297.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  298.  
  299. }
  300.  
  301. /*
  302.  *----------------------------------------------------------------------
  303.  *
  304.  * LfsMarkSegsClean --
  305.  *
  306.  *    Mark the specified segments as clean.
  307.  *
  308.  * Results:
  309.  *    None
  310.  *
  311.  * Side effects:
  312.  *    Seg usage array may be modified.
  313.  *
  314.  *----------------------------------------------------------------------
  315.  */
  316.  
  317. void
  318. LfsMarkSegsClean(lfsPtr, numSegs, segs)
  319.     Lfs        *lfsPtr;    /* File system of interest. */
  320.     int        numSegs;     /* Number of segments in list. */
  321.     LfsSegList    *segs;        /* Segments to mark clean. */
  322. {
  323.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  324.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  325.     register LfsSegUsageEntry  *s;
  326.     int            i, segNumber, first, previous, flags, nextSeg;
  327.     ReturnStatus      status;
  328.     LfsStableMemEntry smemEntry;
  329.  
  330.     /*
  331.      * Build a list of the segment to mark clean. 
  332.      */
  333.     first = previous = -1;
  334.     flags = LFS_STABLE_MEM_MAY_DIRTY;
  335.     for (i = 0; i < numSegs; i++) {
  336.     if (segs[i].segNumber == -1) {
  337.         /*
  338.          * Segments get marked with -1 if we can't clean them.
  339.          */
  340.         continue;
  341.     }
  342.     segNumber = segs[i].segNumber;
  343.  
  344.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNumber, 
  345.                 flags, &smemEntry);
  346.     if (status != SUCCESS) {
  347.         panic("LfsMarkSegClean can't fetch segment %d usage array.",
  348.             segNumber);
  349.         return;
  350.     }
  351.     flags |= LFS_STABLE_MEM_REL_ENTRY;
  352.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  353.     if (s->flags & LFS_SEG_USAGE_CLEAN) { 
  354.         /*
  355.          * Already clean, skip it.
  356.          */
  357.         continue;
  358.     }
  359.     /*
  360.      * Segment is being marked clean. Remove from dirty list if necessary.
  361.      */
  362.     if (s->flags & LFS_SEG_USAGE_DIRTY) { 
  363.         s->flags &= ~LFS_SEG_USAGE_DIRTY;
  364.         cp->numDirty--;
  365.     }
  366.     cp->numClean++;
  367.     s->flags = LFS_SEG_USAGE_CLEAN;
  368.     s->activeBytes = previous;
  369.     LfsStableMemMarkDirty(&smemEntry);
  370.     if (previous == -1) {
  371.         first = segNumber;
  372.     }
  373.     previous = segNumber;
  374.     }
  375.  
  376.     if (previous == -1) {
  377.     /*
  378.      * Nothing to clean. 
  379.      */
  380.     return;
  381.     }
  382.  
  383.     /*
  384.      * Insert the new list into the list of already clean
  385.      * segments. We insert this segment as the second element on
  386.      * the list.  This requires two Fetchs:
  387.      * 1) Update the head of list segment to point at us.
  388.      * 2) Update us to point at what the head of list use to.
  389.      */
  390.     status = LfsStableMemFetch(&(usagePtr->stableMem), cp->cleanSegList, 
  391.             flags, &smemEntry);
  392.     if (status != SUCCESS) {
  393.     panic("LfsMarkSegClean can't fetch usage array.");
  394.     return;
  395.     }
  396.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  397.     nextSeg = s->activeBytes;
  398.     s->activeBytes = previous;
  399.     LfsStableMemMarkDirty(&smemEntry);
  400.  
  401.     status = LfsStableMemFetch(&(usagePtr->stableMem), first, 
  402.             LFS_STABLE_MEM_MAY_DIRTY|LFS_STABLE_MEM_REL_ENTRY, 
  403.             &smemEntry);
  404.     if (status != SUCCESS) {
  405.     panic("LfsMarkSegClean can't fetch usage array.");
  406.     return;
  407.     }
  408.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  409.     s->activeBytes = nextSeg;
  410.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  411.     return;
  412. }
  413.  
  414. /*
  415.  *----------------------------------------------------------------------
  416.  *
  417.  * LfsSetDirtyLevel --
  418.  *
  419.  *    Set the usage level below which a segment is considered dirty.
  420.  *
  421.  * Results:
  422.  *    None
  423.  *
  424.  * Side effects:
  425.  *    Seg usage array may be modified.
  426.  *
  427.  *----------------------------------------------------------------------
  428.  */
  429.  
  430. void
  431. LfsSetDirtyLevel(lfsPtr, dirtyActiveBytes)
  432.     Lfs    *lfsPtr;
  433.     int     dirtyActiveBytes; /* New level. */
  434. {
  435.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  436.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  437.     register LfsSegUsageEntry  *s;
  438.     register int    segNum;
  439.     ReturnStatus      status;
  440.     LfsStableMemEntry smemEntry;
  441.  
  442.  
  443.     cp->dirtyActiveBytes = dirtyActiveBytes;
  444.     for (segNum = 0; segNum < usagePtr->params.numberSegments; segNum++) {
  445.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNum,
  446.             LFS_STABLE_MEM_MAY_DIRTY| 
  447.               ((segNum > 0) ? LFS_STABLE_MEM_REL_ENTRY : 0), 
  448.               &smemEntry);
  449.  
  450.     if (status != SUCCESS) {
  451.         panic("LfsSetDirtyLevel can't fetch usage array block.\n");
  452.     }
  453.      s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  454.     if (s->activeBytes <= dirtyActiveBytes) {
  455.         if (s->flags & (LFS_SEG_USAGE_DIRTY|LFS_SEG_USAGE_CLEAN)) { 
  456.         /*
  457.          * All ready on dirty or clean list then do nothing.
  458.          */
  459.         } else { 
  460.         s->flags |= LFS_SEG_USAGE_DIRTY;
  461.         cp->numDirty++;
  462.         LfsStableMemMarkDirty(&smemEntry);
  463.         }
  464.     } 
  465.     }
  466.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  467.  
  468. }
  469.  
  470.  
  471. /*
  472.  *----------------------------------------------------------------------
  473.  *
  474.  * Lfs_DomainInfo --
  475.  *
  476.  *    Return info about the given domain lfsDomain.
  477.  *
  478.  * Results:
  479.  *    SUCCESS
  480.  *
  481.  * Side effects:
  482.  *    The domain info struct is filled in.
  483.  *
  484.  *----------------------------------------------------------------------
  485.  */
  486. ReturnStatus
  487. Lfs_DomainInfo(domainPtr, domainInfoPtr)
  488.     Fsdm_Domain    *domainPtr;
  489.     Fs_DomainInfo    *domainInfoPtr;
  490. {
  491.     Lfs        *lfsPtr = LfsFromDomainPtr(domainPtr);
  492.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  493.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  494.     int         numBlocks;
  495.  
  496.     /*
  497.      * Compute the number of blocks available for data.
  498.      */
  499.     numBlocks = usagePtr->params.numberSegments * LfsSegSizeInBlocks(lfsPtr) -
  500.                     usagePtr->params.minFreeBlocks;
  501.  
  502.     domainInfoPtr->maxKbytes = LfsBlocksToBytes(lfsPtr, numBlocks) / 1024;
  503.  
  504.  
  505.     /*
  506.      * Compute the number of free blocks available for data.
  507.      */
  508.     numBlocks = cp->freeBlocks - usagePtr->params.minFreeBlocks;
  509.     if (numBlocks < 0) {
  510.     numBlocks = 0;
  511.     }
  512.     domainInfoPtr->freeKbytes = LfsBlocksToBytes(lfsPtr, numBlocks) / 1024;
  513.  
  514. #ifdef sprite
  515.     /*
  516.      * The Sprite df command assumes that the file system reserves 
  517.      * 10% of the disk.  It prints maxKbytes as .9 * maxKbytes and
  518.      * freeKbytes as freeKbytes - .1*maxKbytes.  To get df to look
  519.      * right we adjust the numbers returned. We use /10 rather
  520.      * *.10 to avoid floating point in kernel.
  521.      */
  522.     domainInfoPtr->maxKbytes = (domainInfoPtr->maxKbytes * 10)/9;
  523.     domainInfoPtr->freeKbytes += (domainInfoPtr->maxKbytes/10);
  524. #endif
  525.  
  526.     domainInfoPtr->maxFileDesc = lfsPtr->descMap.params.maxDesc;
  527.     domainInfoPtr->freeFileDesc = lfsPtr->descMap.params.maxDesc -
  528.                   lfsPtr->descMap.checkPoint.numAllocDesc;
  529.     domainInfoPtr->blockSize = FS_BLOCK_SIZE;
  530.     domainInfoPtr->optSize = LfsSegSize(lfsPtr);
  531.  
  532.  
  533.     return(SUCCESS);
  534. }
  535.  
  536.  
  537.  
  538. /*
  539.  *----------------------------------------------------------------------
  540.  *
  541.  * LfsGetLogTail --
  542.  *
  543.  *    Get the next available clean blocks to write the log to.
  544.  *
  545.  * Results:
  546.  *    SUCCESS if log space was retrieved. FS_NO_DISK_SPACE if log
  547.  *    space is not available. FS_WOULD_BLOCK if operation of blocked.
  548.  *
  549.  * Side effects:
  550.  *
  551.  *
  552.  *----------------------------------------------------------------------
  553.  */
  554.  
  555. ReturnStatus
  556. LfsGetLogTail(lfsPtr, cantWait, logRangePtr, startBlockPtr)
  557.     Lfs    *lfsPtr;    /* File system of interest. */
  558.     Boolean    cantWait;      /* TRUE if we can't wait for a clean seg. */
  559.     LfsSegLogRange *logRangePtr;  /* Segments numbers returned. */
  560.     int           *startBlockPtr; /* OUT: Starting offset into segment. */
  561. {
  562.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  563.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  564.     LfsSegUsageEntry *s;
  565.     int        segNumber;
  566.     ReturnStatus      status;
  567.     LfsStableMemEntry smemEntry;
  568.     char errMsg[1024];
  569.  
  570.     if (!cantWait && 
  571.     (cp->numClean <= 
  572.         lfsPtr->usageArray.params.minNumClean + lfsMinCleanThreshold)) {
  573.     LfsSegCleanStart(lfsPtr);
  574.     if (cp->numClean <= lfsPtr->usageArray.params.minNumClean) {
  575.         return FS_WOULD_BLOCK;
  576.     }
  577.     }
  578.     if (cp->currentBlockOffset != -1) {
  579.     /*
  580.      * There is still room in the existing segment. Use it.
  581.      */
  582.     logRangePtr->prevSeg = cp->previousSegment;
  583.     logRangePtr->current = cp->currentSegment;
  584.     logRangePtr->nextSeg =  cp->cleanSegList;
  585.     (*startBlockPtr) = cp->currentBlockOffset;
  586.     return SUCCESS;
  587.     }
  588.     /*
  589.      * Need to location a new segment.
  590.      */
  591.     if (cp->numClean == 0) {
  592.     sprintf(errMsg,
  593.         "LfsGetLogTail: no space (no clean segments) on %s.\n",
  594.         lfsPtr->name);    /* DEBUG */
  595.     if (Timer_OkToWhine(errMsg)) {
  596.         printf(errMsg);
  597.     }
  598.     return FS_NO_DISK_SPACE;
  599.     }
  600.     /*
  601.      * Update the active bytes of the current segment the usage array.
  602.      */
  603.     status = LfsStableMemFetch(&(usagePtr->stableMem), cp->currentSegment, 
  604.             LFS_STABLE_MEM_MAY_DIRTY, &smemEntry);
  605.     if (status == SUCCESS) {
  606.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  607.     s->activeBytes = cp->curSegActiveBytes;
  608.     if (s->activeBytes <= cp->dirtyActiveBytes) {
  609.         s->flags |= LFS_SEG_USAGE_DIRTY;
  610.         cp->numDirty++;
  611.     }
  612.     s->timeOfLastWrite = usagePtr->timeOfLastWrite;
  613.     LfsStableMemMarkDirty(&smemEntry);
  614.     } else {
  615.     panic("LfsGetCleanSeg can't fetch usage array.");
  616.     }
  617.  
  618.     segNumber = cp->cleanSegList;
  619.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNumber, 
  620.             (LFS_STABLE_MEM_MAY_DIRTY| 
  621.              LFS_STABLE_MEM_REL_ENTRY), &smemEntry);
  622.     if (status != SUCCESS) {
  623.     panic("LfsGetCleanSeg can't fetch usage array.");
  624.     return status;
  625.     }
  626.  
  627.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  628.     cp->cleanSegList = s->activeBytes;
  629.  
  630.     logRangePtr->prevSeg = cp->previousSegment = cp->currentSegment;
  631.     logRangePtr->current = cp->currentSegment = segNumber;
  632.     logRangePtr->nextSeg =  cp->cleanSegList;
  633.  
  634.     usagePtr->timeOfLastWrite = 0;
  635.     cp->numClean--;
  636.     s->activeBytes = cp->curSegActiveBytes = 0;
  637.     if (cp->numClean <= lfsPtr->usageArray.params.minNumClean) {
  638.     LfsSegCleanStart(lfsPtr);
  639.     }
  640.     s->flags  &= ~LFS_SEG_USAGE_CLEAN;
  641.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  642.     (*startBlockPtr) = 0;
  643.     return SUCCESS;
  644. }
  645.  
  646. /*
  647.  *----------------------------------------------------------------------
  648.  *
  649.  * LfsSetLogTail --
  650.  *
  651.  *    Set the next available clean blocks to write the log to.
  652.  *
  653.  * Results:
  654.  *    None
  655.  *
  656.  * Side effects:
  657.  *
  658.  *
  659.  *----------------------------------------------------------------------
  660.  */
  661.  
  662. void
  663. LfsSetLogTail(lfsPtr, logRangePtr, startBlock, activeBytes, timeOfLastWrite)
  664.     Lfs    *lfsPtr;    /* File system of interest. */
  665.     LfsSegLogRange *logRangePtr;  /* Segments numbers returned. */
  666.     int    startBlock; /* Starting offset into segment. */
  667.     int    activeBytes;    /* Number of bytes written. */
  668.     int    timeOfLastWrite; /* Youngest block in segment. */
  669. {
  670.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  671.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  672.  
  673.     cp->currentBlockOffset = startBlock;
  674.     if (usagePtr->timeOfLastWrite < timeOfLastWrite) {
  675.     usagePtr->timeOfLastWrite = timeOfLastWrite;
  676.     }
  677.     if (activeBytes > 0) {
  678.     LfsSetSegUsage(lfsPtr, logRangePtr->current, activeBytes);
  679.    }
  680. }
  681.  
  682. /*
  683.  *----------------------------------------------------------------------
  684.  *
  685.  * LfsSegUsageEnoughClean --
  686.  *
  687.  *    Check to see if we have enought clean segment to accept this
  688.  *    data.
  689.  *
  690.  * Results:
  691.  *    TRUE if we do. FALSE if call should wait for some to become 
  692.  *    available.
  693.  *
  694.  * Side effects:
  695.  *    None.
  696.  *
  697.  *----------------------------------------------------------------------
  698.  */
  699.  
  700. Boolean
  701. LfsSegUsageEnoughClean(lfsPtr, dirtyBytes)
  702.     Lfs    *lfsPtr;
  703.     int    dirtyBytes;
  704. {
  705.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  706.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  707.     int    segsAvailable, cleaningThreshold;
  708.  
  709.  
  710.     segsAvailable = cp->numClean - usagePtr->params.minNumClean;
  711.     cleaningThreshold = segsAvailable - lfsMinCleanThreshold;
  712.     if (cleaningThreshold * LfsSegSize(lfsPtr) < dirtyBytes) {
  713.     LfsSegCleanStart(lfsPtr);
  714.     }
  715.     return ((segsAvailable * LfsSegSize(lfsPtr)) > dirtyBytes);
  716. }
  717.  
  718. /*
  719.  *----------------------------------------------------------------------
  720.  *
  721.  * LfsGetSegsToClean --
  722.  *
  723.  *    Return a set of segments to clean.
  724.  *
  725.  * Results:
  726.  *    Number of segments returned.
  727.  *
  728.  * Side effects:
  729.  *
  730.  *
  731.  *----------------------------------------------------------------------
  732.  */
  733.  
  734. int
  735. LfsGetSegsToClean(lfsPtr, maxSegArrayLen, segArrayPtr, minNeededToCleanPtr,
  736.           maxAvailToWritePtr)
  737.     Lfs      *lfsPtr;    /* File system of interest. */
  738.     int      maxSegArrayLen;     /* The maximum number of segment to clean to 
  739.                  * return. */
  740.     LfsSegList     *segArrayPtr;    /* Array of length maxSegArrayLen to return
  741.                  * segments to clean. */
  742.     int        *minNeededToCleanPtr; /* OUT: Minimum number of segments
  743.                        * that should be cleaned. 
  744.                        */
  745.     int        *maxAvailToWritePtr; /* OUT: Maximum number of segments
  746.                        * that should be cleaned. Before
  747.                        * marking the segment as clean.
  748.                        */
  749. {
  750.     int    numberSegs, segNum, blockSize;
  751.     Boolean fullClean;
  752.     int i, j, currentTime;
  753.     LfsSegUsageEntry *s;
  754.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  755.     ReturnStatus      status;
  756.     int        flags;
  757.     LfsStableMemEntry smemEntry;
  758.  
  759.     (*minNeededToCleanPtr) = 0;
  760.     (*maxAvailToWritePtr) = 0;
  761.     numberSegs = 0;
  762.     blockSize = LfsBlockSize(lfsPtr);
  763.     /*
  764.      * For each  segment.
  765.      */
  766.    currentTime = Fsutil_TimeInSeconds();
  767.    flags = LFS_STABLE_MEM_MAY_DIRTY;
  768.    for (segNum = 0; segNum < usagePtr->params.numberSegments; segNum++) {
  769.     /*
  770.      * Execpt the one currently being written.
  771.      */
  772.     if (usagePtr->checkPoint.currentSegment == segNum) { 
  773.         continue;
  774.     }
  775.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNum,  flags, 
  776.                      &smemEntry);
  777.     if (status != SUCCESS) {
  778.         panic("LfsSetDirtyLevel can't fetch usage array block.\n");
  779.         return status;
  780.     }
  781.     flags |= LFS_STABLE_MEM_REL_ENTRY;
  782.     s = (LfsSegUsageEntry *)LfsStableMemEntryAddr(&smemEntry);
  783.     /*
  784.      * Find the proper position in the list for this segment.
  785.      */
  786.     /*
  787.      * Patch to fixed up bad activeBytes.
  788.      */
  789.     if (!(s->flags & (LFS_SEG_USAGE_CLEAN|LFS_SEG_USAGE_DIRTY)) &&
  790.          (s->activeBytes <= usagePtr->checkPoint.dirtyActiveBytes)) {
  791.         s->flags |= LFS_SEG_USAGE_DIRTY;
  792.         usagePtr->checkPoint.numDirty++;
  793.     }
  794.     if (s->flags & LFS_SEG_USAGE_DIRTY) {
  795.         int    age;
  796.         unsigned int blocks, priority;
  797.         /*
  798.          * Besure the age in minutes is not totally bogus because of 
  799.          * startup settings or running the system with a bogus time.
  800.          */
  801.         age = (currentTime - s->timeOfLastWrite)/60;
  802.         if (age > 60*24*365*2) {
  803.         /*
  804.          * If the age is greater that 2 years set it to 2 years.
  805.          */
  806.         age = 60*24*365*2;
  807.         } else if (age <= 0) {
  808.         /*
  809.          * If the age is less or equal to zero set it to 1 minute. 
  810.          */
  811.          age = 1;
  812.         }
  813.         /*
  814.          * To do the  priority caluation without using floating
  815.          * point we scale the byte values into block values
  816.          * and scale the age into minutes.
  817.          */
  818.         if (s->activeBytes != 0) { 
  819.         blocks = LfsBytesToBlocks(lfsPtr, s->activeBytes);
  820.         if (s->activeBytes < 0) {
  821.             blocks = 0;
  822.         }
  823.         priority = ((LfsSegSizeInBlocks(lfsPtr) - blocks) * age) /
  824.                 (LfsSegSizeInBlocks(lfsPtr) + blocks);
  825.         } else {
  826.         /*
  827.          * Give zero size segments highest priority.
  828.          */
  829.         priority = 0x7fffffff;
  830.         }
  831.         /*
  832.          * Find the last element in the list with a priority
  833.          * greater the the current segments.
  834.          */
  835.         for (i = numberSegs-1; i >= 0; i--) {
  836.         if (segArrayPtr[i].priority >= priority) {
  837.             break;
  838.         } 
  839.         }
  840.         /*
  841.          * Extend the array if it is not full already.
  842.          * Insert new seg at specified position by moving all others down.
  843.          * Don't do insert if position is after the end of the array.
  844.          */
  845.         if (numberSegs < maxSegArrayLen) {
  846.         numberSegs++;
  847.         }
  848.  
  849.         if (i < numberSegs-1) { 
  850.         for (j = numberSegs-2; j > i; j--) {
  851.             segArrayPtr[j+1] = segArrayPtr[j];
  852.         }
  853.         segArrayPtr[i+1].segNumber = segNum;
  854.         segArrayPtr[i+1].activeBytes = s->activeBytes;
  855.         segArrayPtr[i+1].priority = priority;
  856.         }
  857.     }
  858.    }
  859.    LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  860.    fullClean = ((lfsPtr->controlFlags & LFS_CONTROL_CLEANALL) != 0);
  861.    /*
  862.     * Set the minimum number to get us above the numSegsToClean
  863.     * threashold. 
  864.     */
  865.    (*minNeededToCleanPtr) = (usagePtr->params.minNumClean + 
  866.                usagePtr->params.numSegsToClean+1) - 
  867.                 usagePtr->checkPoint.numClean;
  868.    if ((*minNeededToCleanPtr) < 0) {
  869.     (*minNeededToCleanPtr) = 0;
  870.    }
  871.    if (fullClean) {
  872.     (*minNeededToCleanPtr) = numberSegs;
  873.    }
  874.    /*
  875.     * Set the max number to write to use half the minimum number or
  876.     * all but the last 10 - whichever is less.
  877.     */
  878.    (*maxAvailToWritePtr) = usagePtr->params.minNumClean / 2;
  879.    if ((*maxAvailToWritePtr) >= usagePtr->checkPoint.numClean-10) {
  880.        (*maxAvailToWritePtr) = usagePtr->checkPoint.numClean-10;
  881.    }
  882.   return numberSegs;
  883. }
  884.  
  885.  
  886. /*
  887.  *----------------------------------------------------------------------
  888.  *
  889.  * LfsSegUsageCheckpointUpdate --
  890.  *
  891.  *    This routine is used to update fields of the seg usage 
  892.  *    checkpoint that change when the checkpoint itself is 
  893.  *    written to the log.
  894.  *
  895.  * Results:
  896.  *    None.
  897.  *
  898.  * Side effects:
  899.  *    None.
  900.  *
  901.  *----------------------------------------------------------------------
  902.  */
  903.  
  904. void
  905. LfsSegUsageCheckpointUpdate(lfsPtr, checkPointPtr, size)
  906.     Lfs     *lfsPtr;     /* File system being checkpointed. */
  907.     char *checkPointPtr; /* Checkpoint region for SegUsage. */
  908.     int     size;         /* Size of checkpoint region. */
  909. {
  910.     LfsSegUsage          *usagePtr = &(lfsPtr->usageArray);
  911.  
  912.     if (size < sizeof(LfsSegUsageCheckPoint)) {
  913.     panic("LfsSegUsageCheckpointUpdate bad checkpoint size.\n");
  914.     }
  915.     (*(LfsSegUsageCheckPoint *) checkPointPtr) = usagePtr->checkPoint;
  916.     return;
  917. }
  918.  
  919.  
  920. extern ReturnStatus LfsSegUsageAttach _ARGS_((Lfs *lfsPtr, 
  921.             int checkPointSize, char *checkPointPtr));
  922. extern Boolean LfsSegUsageCheckpoint _ARGS_((LfsSeg *segPtr, int flags, 
  923.             char *checkPointPtr, int *checkPointSizePtr, 
  924.             ClientData *clientDataPtr));
  925. extern void LfsSegUsageWriteDone _ARGS_((LfsSeg *segPtr, int flags, 
  926.             ClientData *clientDataPtr));
  927. extern Boolean LfsSegUsageClean _ARGS_((LfsSeg *segPtr, int *sizePtr,
  928.             int *numCacheBlocksPtr, ClientData *clientDataPtr));
  929. extern Boolean LfsSegUsageLayout _ARGS_((LfsSeg *segPtr, int flags, 
  930.             ClientData *clientDataPtr));
  931.  
  932. extern ReturnStatus LfsSegUsageDetach _ARGS_((Lfs *lfsPtr));
  933.  
  934. static LfsSegIoInterface segUsageIoInterface = 
  935.     { LfsSegUsageAttach, LfsSegUsageLayout, LfsSegUsageClean,
  936.       LfsSegUsageCheckpoint, LfsSegUsageWriteDone, LfsSegUsageDetach, 0};
  937.  
  938.  
  939. /*
  940.  *----------------------------------------------------------------------
  941.  *
  942.  * LfsSegUsageInit --
  943.  *
  944.  *    Initialize the segment usage array  data structures.  
  945.  *
  946.  * Results:
  947.  *    None
  948.  *    
  949.  * Side effects:
  950.  *
  951.  *----------------------------------------------------------------------
  952.  */
  953.  
  954. void
  955. LfsSegUsageInit()
  956. {
  957.     LfsSegIoRegister(LFS_SEG_USAGE_MOD,&segUsageIoInterface);
  958. }
  959.  
  960.  
  961. /*
  962.  *----------------------------------------------------------------------
  963.  *
  964.  * SegUsageAttach --
  965.  *
  966.  *    Attach routine for the seg usage map. Creates and initializes the
  967.  *    map for this file system.
  968.  *
  969.  * Results:
  970.  *    SUCCESS if attaching is going ok.
  971.  *
  972.  * Side effects:
  973.  *    Many
  974.  *
  975.  *----------------------------------------------------------------------
  976.  */
  977.  
  978. ReturnStatus
  979. LfsSegUsageAttach(lfsPtr, checkPointSize, checkPointPtr)
  980.     Lfs   *lfsPtr;         /* File system for attach. */
  981.     int   checkPointSize;    /* Size of checkpoint data. */
  982.     char  *checkPointPtr;     /* Data from last checkpoint before shutdown. */
  983. {
  984.     LfsSegUsage          *usagePtr = &(lfsPtr->usageArray);
  985.     LfsSegUsageCheckPoint *cp = (LfsSegUsageCheckPoint *) checkPointPtr;
  986.     ReturnStatus status;
  987.  
  988.     /*
  989.      * Allocate and fill in memory data structure for descriptor map.
  990.      */
  991.     usagePtr->params = lfsPtr->superBlock.usageArray;
  992.     usagePtr->checkPoint = *cp;
  993.     usagePtr->timeOfLastWrite = Fsutil_TimeInSeconds();
  994.     /*
  995.      * Load the stableMem and buffer using the LfsStableMem routines.
  996.      */
  997.     status = LfsStableMemLoad(lfsPtr, &(usagePtr->params.stableMem), 
  998.             checkPointSize - sizeof(LfsSegUsageCheckPoint), 
  999.             checkPointPtr + sizeof(LfsSegUsageCheckPoint), 
  1000.             &(usagePtr->stableMem));
  1001.     if (status != SUCCESS) {
  1002.     LfsError(lfsPtr, status,"Can't loading descriptor map stableMem\n");
  1003.     return status;
  1004.     }
  1005.     return status;
  1006. }
  1007.  
  1008. /*
  1009.  *----------------------------------------------------------------------
  1010.  *
  1011.  * SegUsageDetach --
  1012.  *
  1013.  *    Detach routine for the seg usage array. Destory the
  1014.  *    array for this file system.
  1015.  *
  1016.  * Results:
  1017.  *    SUCCESS if dettach is going ok.
  1018.  *
  1019.  * Side effects:
  1020.  *    Many
  1021.  *
  1022.  *----------------------------------------------------------------------
  1023.  */
  1024.  
  1025. ReturnStatus
  1026. LfsSegUsageDetach(lfsPtr)
  1027.     Lfs   *lfsPtr;         /* File system for attach. */
  1028. {
  1029.     LfsSegUsage          *usagePtr = &(lfsPtr->usageArray);
  1030.  
  1031.     return LfsStableMemDestory(lfsPtr,     &(usagePtr->stableMem));
  1032. }
  1033.  
  1034. /*
  1035.  *----------------------------------------------------------------------
  1036.  *
  1037.  * SegUsageCheckpoint --
  1038.  *
  1039.  *    Routine to handle checkpointing of the descriptor map data.
  1040.  *
  1041.  * Results:
  1042.  *    TRUE if more data needs to be written, FALSE if this module is
  1043.  *    checkpointed.
  1044.  *
  1045.  * Side effects:
  1046.  *    Many
  1047.  *
  1048.  *----------------------------------------------------------------------
  1049.  */
  1050.  
  1051. Boolean
  1052. LfsSegUsageCheckpoint(segPtr, flags,checkPointPtr, checkPointSizePtr, 
  1053.             clientDataPtr)
  1054.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  1055.     char   *checkPointPtr;      /* Buffer to write checkpoint data. */
  1056.     int       flags;        /* Flags. */
  1057.     int       *checkPointSizePtr;  /* Bytes added to the checkpoint area.*/
  1058.     ClientData *clientDataPtr;
  1059. {
  1060.     LfsSegUsage          *usagePtr = &(segPtr->lfsPtr->usageArray);
  1061.     LfsSegUsageCheckPoint *cp = (LfsSegUsageCheckPoint *) checkPointPtr;
  1062.     int        size;
  1063.     Boolean    full;
  1064.  
  1065.     *cp = usagePtr->checkPoint;
  1066.     size = sizeof(LfsSegUsageCheckPoint);
  1067.  
  1068.     full = LfsStableMemCheckpoint(segPtr, checkPointPtr + size, flags,
  1069.         checkPointSizePtr, clientDataPtr,
  1070.         &(usagePtr->stableMem));
  1071.     if (!full) { 
  1072.     *checkPointSizePtr = (*checkPointSizePtr) + size;
  1073.     }
  1074.     return full;
  1075.  
  1076. }
  1077.  
  1078. /*
  1079.  *----------------------------------------------------------------------
  1080.  *
  1081.  * SegUsageWriteDone --
  1082.  *
  1083.  *    Routine to handle finishing of a checkpoint.
  1084.  *
  1085.  * Results:
  1086.  *    None
  1087.  *
  1088.  * Side effects:
  1089.  *    Many
  1090.  *
  1091.  *----------------------------------------------------------------------
  1092.  */
  1093.  
  1094. void
  1095. LfsSegUsageWriteDone(segPtr, flags, clientDataPtr)
  1096.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  1097.     int       flags;        /* Flags for checkpoint */
  1098.     ClientData *clientDataPtr;
  1099. {
  1100.     LfsSegUsage          *usagePtr = &(segPtr->lfsPtr->usageArray);
  1101.  
  1102.     LFS_STATS_ADD(segPtr->lfsPtr->stats.segusage.blocksWritten, 
  1103.         (LfsSegSummaryBytesLeft(segPtr) / sizeof(int)));
  1104.     LfsStableMemWriteDone(segPtr, flags, clientDataPtr, 
  1105.               &(usagePtr->stableMem));
  1106.     return;
  1107.  
  1108. }
  1109.  
  1110.  
  1111. /*
  1112.  *----------------------------------------------------------------------
  1113.  *
  1114.  * LfsSegUsageClean --
  1115.  *
  1116.  *    Routine to handle cleaning of descriptor map data.
  1117.  *
  1118.  * Results:
  1119.  *    TRUE if more data needs to be written, FALSE if this module is
  1120.  *    happy for the time being.
  1121.  *
  1122.  * Side effects:
  1123.  *    
  1124.  *
  1125.  *----------------------------------------------------------------------
  1126.  */
  1127.  
  1128. Boolean
  1129. LfsSegUsageClean(segPtr, sizePtr, numCacheBlocksPtr, clientDataPtr)
  1130.     LfsSeg *segPtr;    /* Segment containing data to clean. */
  1131.     int *sizePtr;        /* Size of cleaning. */
  1132.     int *numCacheBlocksPtr;
  1133.     ClientData *clientDataPtr;
  1134. {
  1135.     LfsSegUsage          *usagePtr = &(segPtr->lfsPtr->usageArray);
  1136.     Boolean    full;
  1137.  
  1138.     full =  LfsStableMemClean(segPtr, sizePtr, numCacheBlocksPtr, clientDataPtr,
  1139.             &(usagePtr->stableMem));
  1140.  
  1141.     LFS_STATS_ADD(segPtr->lfsPtr->stats.segusage.blocksCleaned, 
  1142.         *sizePtr/usagePtr->stableMem.params.blockSize);
  1143.     return full;
  1144.  
  1145. }
  1146.  
  1147.  
  1148.  
  1149. /*
  1150.  *----------------------------------------------------------------------
  1151.  *
  1152.  * LfsSegUsageLayout --
  1153.  *
  1154. *    Routine to handle layingout of segUsage data.
  1155.  *
  1156.  * Results:
  1157.  *    TRUE if more data needs to be written, FALSE if this module is
  1158.  *    happy for the time being.
  1159.  *
  1160.  * Side effects:
  1161.  *    
  1162.  *
  1163.  *----------------------------------------------------------------------
  1164.  */
  1165.  
  1166. Boolean
  1167. LfsSegUsageLayout(segPtr, flags, clientDataPtr)
  1168.     LfsSeg *segPtr;    /* Segment containing data to clean. */
  1169.     int flags; /* Layout flags. */
  1170.     ClientData *clientDataPtr;
  1171. {
  1172.     LfsSegUsage          *usagePtr = &(segPtr->lfsPtr->usageArray);
  1173.  
  1174.     if ((flags & LFS_CLEANING_LAYOUT) != 0) {
  1175.     return FALSE;
  1176.     }
  1177.     return  LfsStableMemLayout(segPtr, flags, 
  1178.                 clientDataPtr, &(usagePtr->stableMem));
  1179. }
  1180.  
  1181.